function Filio(path) {
  this.filePath = path;

  // Open file given in path
  this.file = function() {
    var openFile = Components.classes["@mozilla.org/file/local;1"]
      .createInstance(Components.interfaces.nsILocalFile);
	  openFile.initWithPath(this.filePath);
	  return openFile;
	}
}

// Create the file specified in the constructor
//
// Example:
// var f = new Filio('/folder/test.txt');
// f.create(); // Creates a new file called test.txt
Filio.prototype.create = function() {
  this.file().create(0x00, 0664);
}

// Checks if the file already exists, returning true or false
//
// Example:
// var f = new Filio('/folder/test.txt');
// var fileExists = f.exists(); // False if file doesn't exist yet, true if it does
Filio.prototype.exists = function() {
  return this.file().exists();
}

// Read contents of file
//
// Paramaters:
//   line [optional]: Read contents of a line, with the first line designated as line 0
//   startPos [optional]: Point in file to start reading
//   chars [optional]: Number of characters to read
// If no line is given, entire file will be read
// If no startPos is given, entire line will be read
// if no chars is given, rest of line starting at startPos will be read
// Remember, character and line numbering start at 0, not 1
//
// Example:
// var f = new Filio('/folder/test.txt');
// var allFileData = f.read(); // Read entire file
// var firstLine = f.read(0); // Read first line (line 0)
// var someOfFirstLine = f.read(0, 0, 5); // Read first 5 characters of line 0
Filio.prototype.read = function(line, startPos, chars) {
  try {
    // Read all data from file
	  var data = new String();
	  var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]
	    .createInstance(Components.interfaces.nsIFileInputStream);
	  var sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
	    .createInstance(Components.interfaces.nsIScriptableInputStream);
	  fis.init(this.file(), 1, 0, false);
	  sis.init(fis);
	  data += sis.read(-1);
	  sis.close();
	  fis.close();
	  
	  var lines = data.split("\n");
	  if(arguments.length == 1) {
	    // Read entire line
      return lines[line];
	  } else if(arguments.length == 2) {
	    // Read line starting at startPos and ending at end of line
	    return lines[line].substring(startPos, lines[line].length);
	  } else if(arguments.length == 3) {
	    // Read given number of characters at given line starting at startPos
	    return lines[line].substr(startPos, chars);
	  } else {
	    // Read entire file
	    return data;
	  }
	}	catch(e) {
		return false;
	}
}

// Write data to file, erasing all previous data
//
// Parameters:
//   data [required]: Data to write to file
//   line [optional]: Line to overwrite
// If no line is given, entire file will be overwritten
// Remember, character and line numbering start at 0, not 1
//
// Example:
// var f = new Filio('/folder/test.txt');
// f.write('JS is epic'); // Overwrite entire file with this data
// f.write('I guess JS is just okay', 2); // Overwrite line 2 with this data
Filio.prototype.write = function(data, line) {
  try {
	  var fos = Components.classes["@mozilla.org/network/file-output-stream;1"]
	    .createInstance(Components.interfaces.nsIFileOutputStream);
	  // Overwrite entire file
		var flags = 0x02 | 0x08 | 0x20;
		
		// Only overwrite one line with data
		if(arguments.length == 2) {
		  var fileData = this.read();
		  var lines = fileData.split("\n");
		  // Replace line data with given data
		  lines[line] = data;
		  data = "";
		  // Combine array into one string to write to file
		  for(i = 0; i < lines.length; i++) {
		    data += lines[i];
		    // Add newline character to end of line for every line except last
		    if(i < lines.length - 1) {
		      data += "\n";
		    }
		  }
		}
		
		// Write data to file
		fos.init(this.file(), flags, 0664, 0);
		fos.write(data, data.length);
		fos.close();
		return true;
	}	catch(e) {
		return false;
	}
}

// Insert data at a point in file
//
// Parameters:
//   data [required]: Data to insert to file
//   startPos [optional]: Point to start inserting, relative to first character in file
//   line [optional]: Line to insert data to
// If line argument is given, startPos becomes relative to first character in that line
// If no startPos argument is given, data will be inserted at beginning of file
// Remember, character and line numbering start at 0, not 1
//
// Example:
// var f = new Filio('/folder/test.txt');
// f.insert('First and foremost', 0); // Data added to beginning of file
// f.insert('Starting line 2', 0, 2); // Data added to beginning of line 2
// f.insert('wheee', 2, 5); // Data added after third character (character 2) in line 5
Filio.prototype.insert = function(data, startPos, line) {
  // Insert data at beginning of file of no start position is given
  if(arguments.length == 1) {
    this.insert(data, 0);
    return true;
  }

  var fileData = this.read();
  if(arguments.length == 2) {
    // Start position based on number of characters in file
    var iterateData = fileData.split("");
  } else if(arguments.length == 3) {
    // Start position based on position in certain line
    var lines = fileData.split("\n");
    var iterateData = lines[line];
  }
  
  // Add data at specified point
  var newString = new String();
  for(i = 0; i < iterateData.length; i++) {
    if(i == startPos) {
      newString += data;
    }
    newString += iterateData[i];
  }
  
  if(arguments.length == 2) {
    // Overwrite file with new string
    this.write(newString);
  } else if(arguments.length == 3) {
    // Overwrite specified line with new string
    this.write(newString, line);
  }
}

// Append data to end of file
//
// Parameters:
//   data [required]: Data to append to file
//   line [required]: Line to append data to
// If no line is given, data will be appendded to end of file
// Remember, character and line numbering start at 0, not 1
// 
// Example:
// var f = new Filio('/folder/test.txt');
// f.append('\n P.S. I love you'); // Data added to end of file
// f.append(' Wait, Im not done yet', 2); // Data added to the end of line 2
Filio.prototype.append = function(data, line) {
  if(arguments.length == 1) {
    // Read entire file
    var fileData = this.read();
    // Remove trailing newline and add new data
    var newData = fileData.substring(0, fileData.length - 1) + data;
    this.write(newData);
  } else if (arguments.length == 2) {
    // Only read one line
    var fileData = this.read(line);
    // Remove trailing newline and add new data
    var newData = fileData.substring(0, fileData.length - 1) + data;
    this.write(newData, line);
  }
}

// Erase characters from file
//
// Parameters:
//   startPos [required]: Point to start deleting, relative to first character in file
//   chars [required]: Number of characters to delete
//   line [optional]: Line to erase characters in
// If line argument is given, startPos becomes relative to first character in that line
// Remember, character and line numbering start at 0, not 1
//
// Example:
// var f = new Filio('/folder/test.txt');
// f.erase(0, 5); // Erase first 5 characters from file
// f.erase(0, 5, 3); // Erase first 5 characters from line 3
Filio.prototype.erase = function(startPos, chars, line) {
  var fileData = this.read();
  
  if(arguments.length == 2) {
    // Split entire file
    var allChars = fileData.split("");
  } else if(arguments.length == 3) {
    // Split given line
    var lines = fileData.split("\n");
    var lineData = lines[line];
    var allChars = lineData.split("");
  }
  
  // Remove number of characters
  allChars.splice(startPos, chars);
  // Make array one string to write to file
  var newString = allChars.join("");
  
  // Write to file
  if(arguments.length == 2) {
    this.write(newString);
  } else if(arguments.length == 3) {
    this.write(newString, line);
  }
}

// Get the number of characters in file or line
//
// Parameters:
//   line [optional]: Line to count characters in
// If no line argument is given, will return number of characters in file
// Remember, character and line numbering start at 0, not 1
//
// Example:
// var f = new Filio('/folder/test.txt');
// var linesInFile = f.getChars();
// var linesInLineTwo = f.getChars(2);
Filio.prototype.getChars = function(line) {
  if(arguments.length == 0) {
    // Get characters for entire file
    var fileData = this.read();
    var allChars = fileData.split("");
    // Don't count newline characters
    return allChars.length - this.getLines();
  } else if(arguments.length == 1) {
    // Get characters for given line
    var fileData = this.read(line);
    var allChars = fileData.split("");
    return allChars.length;
  }
}

// Get number of lines in file
// 
// Example:
// var f = new Filio('/folder/test.txt');
// var lineCount = f.getLines();
Filio.prototype.getLines = function() {
  var fileData = this.read();
  var lines = fileData.split("\n");
  return lines.length - 1;
}
